[TOC]
小程序教程
🔰第1阶段
🕒开发工具下载和安装
小程序开发工具下载地址:
https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html
🕒创建项目
- 可以新建,也可以导入原有项目
- 需要去注册一个小程序以获得AppId, 当然也可以使用测试号
🕒新建页面
(1) 新增页面
打开app.json文件, 在里面新增一个"我的"的页面, 注意格式:
- 在"pages"里添加
"pages/my/my",
- 需要使用双引号包起来, 后面加逗号
- 最后一条不用加逗号, 加了会报错
- 按ctrl+s 进行保存(也可以在菜单栏的文件里设置自动保存)
{
"pages":[
"pages/index/index",
"pages/my/my",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle":"black"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
(2) 每个页面的4个相关文件
在右边的pages文件夹里, 会多出一个my文件夹, 里面有几个文件:
- my.wxml 用来编写页面内容的
- my.wxss 用来写样式装饰内容的
- my.js 用来给页面添加行为的
- my.json用来配置页面的, 比如导航栏的标题
(3) 查看页面
- 点击菜单栏的编译模式, 点击添加编译模式
- 把
pages/index/index
改成pages/my/my
, 点击确定 - 刷新页面即可
(4) 配置页面
修改导航栏标题, 在my.json里添加
"navigationBarTitleText": "个人中心"
修改背景颜色, 在my.json里添加
"navigationBarBackgroundColor": "#c03d37"
{ "usingComponents": {}, "navigationBarTitleText": "个人中心", "navigationBarBackgroundColor": "#c03d37" }
🕒小程序组件
- view 容器组件(块级组件)
- text 文本组件(行内组件)
- 按钮和图标
- 表单组件
- 输入框
- 单选框
- 多选框
- 下拉列表等
- 音频和视频
- audio 音频
- video 视频
- 图片组件 image
- 链接组件 navigator
🕒给组件添加样式
(1) 全局样式
在app.wxss里设置的样式是全局样式, 所有页面只要匹配得上都会有效果
(2) 页面根容器(根标签)的样式
比如在my.wxss里, 写以下代码
page {
background: gray; /*把页面背景设置为灰色*/
}
(3) 对某个组件(标签)设置样式
view{
border: 1px solid red; /*给所有的view组件添加边框*/
}
wxml代码
<view class="red">
view组件1
</view>
<view class="red">
view组件2
</view>
(4) 给某一类的组件(标签)添加样式
.red {
/* 给所有含有class="red"的组件的字体颜色变成红色 */
color: red;
}
wxml代码
<view class="red">
这是个view组件
</view>
<text class="red">
这是个text组件
</text>
🕒配置小程序底部tab栏
(1) 准备工作
- 新建4个页面: film(电影), cinema(影院), video(视频), my(我的)
- 每个页面随便写点什么内容
- 准备4个tab栏对应的图片, 每个tab栏2张图片
(2) app.json 配置文件详解
{
// 页面路径(地址)
"pages": [
"pages/film/film",
"pages/cinema/cinema",
"pages/video/video",
"pages/my/my"
],
"window": {
// 下拉 loading 的样式不用管
"backgroundTextStyle": "dark",
// 导航栏背景颜色
"navigationBarBackgroundColor": "#c03d37",
// 导航栏文字
"navigationBarTitleText": "百色电影",
// 导航栏文字颜色
"navigationBarTextStyle": "white"
},
"style": "v2",
"sitemapLocation": "sitemap.json",
"tabBar": {
// tab栏字体默认颜色
"color": "#000000",
// tab栏被选中时的字体颜色
"selectedColor": "#c03d37",
"list": [{
// 页面路径(地址)
"pagePath": "pages/film/film",
// tab栏文字
"text": "首页",
// tab栏默认图片
"iconPath": "./img/film.png",
// tab栏被选中时的图片
"selectedIconPath": "./img/filming.png"
},
{
"pagePath": "pages/cinema/cinema",
"text": "影院",
"iconPath": "./img/cinema.png",
"selectedIconPath": "./img/cinemaing.png"
},
{
"pagePath": "pages/video/video",
"text": "视频",
"iconPath": "./img/video.png",
"selectedIconPath": "./img/videoing.png"
},
{
"pagePath": "pages/my/my",
"text": "我的",
"iconPath": "./img/my.png",
"selectedIconPath": "./img/mying.png"
}
]
}
}
🕒编写静态页面
必备知识: 弹性盒子
- display: flex 把一个元素设置为弹性盒子
- align-items 垂直对齐方式
- flex-start 顶部对齐
- center 垂直居中
- flex-start 底部对齐
- justify-content 水平对齐方式
- flex-start 左对齐
- center 水平居中
- flex-end 右对齐
- space-around 分散对齐
- space-between 两端对齐
- flex-grow 剩余空间分配
- 对子元素(组件)进行设置
- 子元素都设置为1, 表示把剩余空间平均分配, 每个子元素获得1份
- 对某个子元素设置为1, 表示把剩余空间分成1分, 全给了该子元素(常用)
首页代码
film.wxml
<!-- 轮播图 -->
<image class="swiper" src="https://static.maizuo.com/v5/upload/6f5e10201aaea65b311d7ab562ba097c.jpg?x-oss-process=image/quality,Q_70"></image>
<!-- tab栏 -->
<view class="tabs">
<text class="tab active">热映</text>
<text class="tab">待映</text>
<text class="tab">经典</text>
</view>
<!-- 电影列表 -->
<view class="list">
<!-- 每一部电影 -->
<view class="item">
<image class="img" src="https://pic.maizuo.com/usr/movie/6d31257bd0c897f0a953b7097853d627.jpg"></image>
<view class="text">
<view>我和我的父辈</view>
<view> 观众评分 <text class="yellow">7</text></view>
<view>主演:吴京|章子怡|徐峥|沈腾</view>
<view>中国大陆 | 100分钟</view>
</view>
<view class="buy">购票</view>
</view>
<view class="item">
<image class="img" src="https://pic.maizuo.com/usr/movie/6d31257bd0c897f0a953b7097853d627.jpg"></image>
<view class="text">
<view>我和我的父辈</view>
<view> 观众评分 <text class="yellow">7</text></view>
<view>主演:吴京|章子怡|徐峥|沈腾</view>
<view>中国大陆 | 100分钟</view>
</view>
<view class="buy">购票</view>
</view>
<view class="item">
<image class="img" src="https://pic.maizuo.com/usr/movie/6d31257bd0c897f0a953b7097853d627.jpg"></image>
<view class="text">
<view>我和我的父辈</view>
<view> 观众评分 <text class="yellow">7</text></view>
<view>主演:吴京|章子怡|徐峥|沈腾</view>
<view>中国大陆 | 100分钟</view>
</view>
<view class="buy">购票</view>
</view>
</view>
film.wxss 代码
page {
/* 整个页面的背景颜色 */
background-color: #f4f4f4;
}
.swiper {
width: 100%;
}
.tabs {
background-color: #fff;
/* 设置辅助边框 */
/* border: 1px solid red; */
/* 高度44px, 88rpx, 用rpx可以自动适配 */
height: 88rpx;
display: flex;
/* 垂直居中 */
align-items: center;
justify-content: space-around;
}
.tab {
/* border: 1px solid green; */
height: 100%;
display: flex;
align-items: center;
}
.active {
border-bottom: 2px solid #c03d37;
}
/* 电影列表 */
.list {
margin-top: 20rpx;
/* border: 1px solid red; */
}
.item {
padding-left: 30rpx;
padding-right: 30rpx;
height: 218rpx;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #fff;
}
.item image {
width: 132rpx;
height: 200rpx;
}
.item .text {
margin-left: 20rpx;
flex-grow: 1;
}
.item .buy {
border: 2rpx solid #c03d37;
padding: 10rpx 20rpx;
color: #c03d37;
}
.item .yellow {
color:#ffb232;
}
🔰第2阶段
最好新建一个demo页面, 专门用来研究新知识
🕒 绑定点击事件
(1) 一个简单的例子
demo.wxml
<button type="primary" bindtap="test">按钮</button>
demo.js
Page({
test(event) {
console.log(22222);
console.log(event); // 事件对象
},
})
(2) 调试器和控制台
- 上面代码
console.log(22222);
意思是在控制台打印22222 - 控制台打开步骤: 左上角
调试器
=>右下角Console
=> 右下角侧边栏info
展示的就是打印的信息 - errors 展示的错误信息
- warnings 展示的是警告信息
🕒 渲染页面
(1) data和setData
data数据的存放的地方
需要在页面展示的数据放在data:{}
里, 如下:
data里存放了两个数据, 一个是title, 它的值是'小程序实训', 另一个是user, 存放了一个用户的信息, 这里data可以理解成一个大容器, 而title和user都是一个小容器, 用来存放数据
Page({
data: {
title: '小程序实训',
user: {
name: '张三',
age: 18
}
}
})
展示数据
data里的数据可以放在wxml里进行展示
<view>
标题: {{title}}
</view>
<view>
<text>
姓名: {{user.name}}
</text>
<text>
年龄: {{user.age}}
</text>
</view>
setData修改数据
demo.wxml
<view>
标题: {{title}}
</view>
<view>
<text>
姓名: {{user.name}}
</text>
<text>
年龄: {{user.age}}
</text>
</view>
<button type="primary" bindtap="change">修改</button>
demo.js
// pages/demo/demo.js
Page({
data: {
title: '小程序实训',
user: {
name: '张三',
age: 18
}
},
change() {
this.setData({
title: 'web前端实训',
user: {
name: '李四',
age: 20
}
})
}
})
(2) 列表展示(列表渲染)
简单列表展示
demo.wxml
<view>狂飙演员列表</view>
<view wx:for="{{list}}">
<text>{{index+1}}.</text>
<text>{{item}}</text>
</view>
demo.js
Page({
data: {
list: ['张译', '张颂文', '李一桐', '张志坚', '吴刚', '倪大红', '程隆妮', '高叶']
},
})
复杂数据列表
demo.js
Page({
data: {
list: [{
name: '张译',
age: 18,
address: '广西'
},
{
name: '张颂文',
age: 19,
address: '广西'
},
{
name: '李一桐',
age: 20,
address: '广东'
},
{
name: '张志坚',
age: 18,
address: '广东'
},
{
name: '吴刚',
age: 17,
address: '广南'
},
{
name: '倪大红',
age: 33,
address: '广南'
},
{
name: '程隆妮',
age: 22,
address: '广北'
},
{
name: '高叶',
age: 20,
address: '广北'
},
]
},
})
demo.wxml
<view>狂飙演员列表</view>
<view wx:for="{{list}}">
<text>{{index+1}}.</text>
<text>{{item.name}}</text>
<text>{{item.age}}</text>
</view>
(3) 条件渲染
根据条件来进行渲染, 就是满足条件就显示, 不满足就不显示
例1. wx:if
demo.js
Page({
data: {
isMan: true
},
})
demo.wxml
<view wx:if="{{isMan}}">臭男人</view>
例2. wx:if和wx:else
demo.wxml
<view wx:if="{{isRain}}">雨天</view>
<view wx:else>晴天</view>
<button type="primary" bindtap="change">切换</button>
demo.js
Page({
data: {
isRain:true
},
change() {
this.setData({
isRain: !this.data.isRain
})
},
})
🕒 获取数据
文档地址: 文档 => api => 网络 => wx.request
例1. 通过按钮获取数据并打印
demo.wxml
<button type="primary" bindtap="getData">获取数据</button>
demo.js
Page({
data: {
},
// 获取数据的方法
getData() {
wx.request({
url: 'http://81.71.65.4:3008/film/list',
success(res) {
console.log(res.data)
}
})
}
})
点击按钮时, 会出现以下错误, 原因是小程序只支持https的接口, 并且接口地址需要到小程序控制台去配置允许访问(称为合法域名)
解决办法: 开发时只需要在小程序右上角 详情 => 本地配置 => 勾选不校验合法域名......
例2. 获取数据并渲染
第一步: 在data里添加变量list
用来存放电影列表
page({
list: []
})
第二步: 请求数据, 把获取到的列表数据存放入data里的list容器
可以通过控制台的AppData查看数据存放情况
// demo.js
Page({
data: {
list: []
},
// 获取数据的方法
getData() {
wx.request({
url: 'http://81.71.65.4:3008/film/list',
// 需要用箭头函数的写法
success: (res)=> {
this.setData({
list: res.data.data
})
}
})
}
})
第三步: 使用前面的列表渲染进行列表展示
demo.wx.ml代码
<button type="primary" bindtap="getData">获取数据</button>
<view wx:for="{{list}}">
<text>电影名称: {{item.name}}</text>
<image src="{{item.poster}}"></image>
</view>
🕒 生命周期函数
生命周期函数, 是满足条件就会自动执行的函数, 其中用得最多的是onLoad和onShow
小程序有以下生命周期函数
- onLoad 生命周期函数--监听页面加载`
- onReady 生命周期函数--监听页面初次渲染完成
- onShow 生命周期函数--监听页面显示
- onHide 生命周期函数--监听页面隐藏
- onUnload 生命周期函数--监听页面卸载
- onPullDownRefresh 页面相关事件处理函数--监听用户下拉动作
- onReachBottom 页面上拉触底事件的处理函数
- onShareAppMessage 用户点击右上角分享
🕒 动态页面
动态页面指的是跟后端有数据交互的页面, 否则就叫静态页面
- 在data里设置
list
变量用来存放要展示的列表 - 在onShow或者onLoad生命周期里调用获取数据的方法
- 成功获取数据后, 把数据存入data的
list
里 - 使用页面渲染(列表和条件渲染)来展示页面
将首页变成动态页面
作业: 把视频页面变成动态页面
🕒 函数传参和接口传参
(1) 函数传参
调用一个函数时, 小括号里可以传入参数, 传入不同的参数, 则结果就不一样
function add(a,b) {
var sum = a+b;
console.log(sum);
}
add(10,20); // 打印30
add(20,30); // 打印50
(2) 接口传参
什么是请求参数? 就是请求数据的时候告诉服务器端你要什么样的数据
- 在文档上演示不同的接口参数, 返回不同的内容
(3) 项目应用
🔰第3阶段
🕒 路由跳转和传参
🔰第4阶段
🕒 小程序授权
🕒 小程序登录
🔰第5阶段
🕒 轮播图
🕒 tab栏切换
(4) 项目详情配置
- 基本信息配置
- 本地配置
(5) 小程序控制台配置
登录小程序: https://mp.weixin.qq.com/
(1) 版本管理
- 上传代码获得体验版, 体验版需要添加权限才可以访问
- 体验版转正式版
- 腾讯审核通过后就变正式版, 所有人都可以访问
(2) 成员管理
(3) 开发管理
- 开发者id和密钥
- 服务器域名配置
(6) 小程序使用npm模块
- 勾选使用npm
- 初始化package.json npm init
- npm i 安装依赖
- 构建项目
✔静态页面
- 使用小程序组件
- view 相当于 div
- text 相当于span
- img变为image
- 地图,音视频,画布等
- ......
- 使用 rpx 作为单位,这个屏幕的宽度为 750rpx
- page{} 该页面的最外层的容器
- 页面之间的样式不会相互影响, 因为小程序本质上是多页应用
- app.wxss是入口的样式, 在这里可以通过@import去加载其它样式
- 底部 tab 配置 文档=>框架=>全局配置=>tabBar
- 开放数据 文档=>组件=>开放能力=>open-data (停用了)
- 编译模式, 编译模式添加启动参数
// 列表跳详情的时候, 会带上id, 比如 url="/detail/detail?id=xxxx"
// 如果此时切换到了detail页面的模式, 刷新数据就没有了
// 这个时候可以编辑detail页面的编译模式, 添加启动参数即可解决问题
- 在小程序中使用 vant-ui
https://vant-contrib.gitee.io/vant-weapp/#/home // 文档地址
图片的各种模式
<view> <text>不保持纵横比缩放图片,使图片完全适应(默认)</text> <image style="width: 150px;height: 150px;border: 1px solid red;padding:5px;" mode="aspectFill" src="../../img/pic.jpg"></image> </view> <view> <text>保持纵横比缩放图片,使图片的长边能完全显示出来</text> <image style="width: 150px;height: 150px;border: 1px solid red;padding:5px;" mode="aspectFit" src="../../img/pic.jpg"></image> </view> <view> <view>不缩放图片,只显示图片的中间区域</view> <image style="width: 250px;height: 250px;border: 1px solid red;padding:5px;" mode="center" src="../../img/pic.jpg"></image> </view> <view> <view>不缩放图片,只显示图片的左边区域</view> <image style="width: 250px;height: 250px;border: 1px solid red;padding:5px;" mode="left" src="../../img/pic.jpg"></image> </view> <view> <view>缩放模式,宽度不变,高度自动变化,保持原图宽高比不变</view> <image style="width: 250px;border: 1px solid red;padding:5px;" mode="widthFix" src="../../img/pic.jpg"></image> </view> <view> <view>缩放模式,高度不变,宽度自动变化,保持原图宽高比不变</view> <image style="width: 150px;height: 250px;border: 1px solid red;padding:5px;" mode="heightFix" src="../../img/pic.jpg"></image> </view>
✔小程序生命周期
小程序有以下生命周期
- onLoad 生命周期函数--监听页面加载
- onReady 生命周期函数--监听页面初次渲染完成
- onShow 生命周期函数--监听页面显示
- onHide 生命周期函数--监听页面隐藏
- onUnload 生命周期函数--监听页面卸载
- onPullDownRefresh 页面相关事件处理函数--监听用户下拉动作
- onReachBottom 页面上拉触底事件的处理函数
- onShareAppMessage 用户点击右上角分享
注意:
- onLoad 只会在小程序中执行一次,比如当前页面是 a 页面,我们在 onLoad 发送请求去获取数据,然后我们切到 b 页面,再切回 a 页面的时候,onLoad 不会再触发,也就是不会再重新发请求获取数据
- onShow 跟 onLoad 不同,每次切回 a 页面的时候都会触发这个生命周期函数
- 所以到底是在 onLoad 发请求还是在 onShow 发请求,要根据实际的业务去做
✔ajax请求获取数据
前言
- 小程序只支持 https
- 需要到小程序后台配置域名白名单
- 项目中请求了非 https 和不在域名白名单上的接口会报错
- 开发时可以取消域名校验,就可以请求任意接口,设置方法 小程序右上角详情 =》本地设置 => 不校验合法域名...
(1) 发送请求
文档地址 文档首页 => api => 网络 => 发起请求
// 示例
wx.request({
url: "test.php", //仅为示例,并非真实的接口地址
// 请求参数
data: {
x: "",
y: "",
},
method: "get", // 请求类型
header: {
"content-type": "application/json", // 默认值
},
// 成功的回调, 若要获得this,需要使用箭头函数
success(res) {
console.log(res.data);
},
// 失败的回调
fail(error) {
console.log(error);
},
// 不管是成功还是失败都会调用此方法
complete() {
console.log("done");
},
});
(2) 使用 promise 封装请求
1. app/request.js
// 封装微信请求
let env = "prod";
let baseUrl = "";
if (env === "dev") {
// 本地地址
baseUrl = "http://localhost:3002";
} else if (env === "prod") {
baseUrl = "http://81.71.65.4:3002";
}
const request = (url,data={},method="get")=> {
wx.showLoading({
title: '努力加载中...',
})
let token = wx.getStorageSync("token");
return new Promise((resolve,reject)=> {
wx.request({
url: baseUrl + url,
method,
data,
header: {
"user-token": token,
},
success(res){
if (res.data.code == 666) {
resolve(res.data);
} else {
wx.showToast({
title: '请求失败',
icon:'error'
})
reject(res.data);
}
},
fail(err) {
console.log(err);
reject(err.errMsg);
},
// 不管请求成功还是失败都会调用此函数
complete() {
wx.hideLoading();
}
})
});
}
export default request;
(3) 统一管理请求
api/index.js
// 统一管理请求
import request from './request';
export const flowerList = (data={})=> {
return request('/flower/list2',data);
}
export const flowerDetail = (data={})=> {
return request('/flower/detail',data);
}
- 挂载到 app,在页面中就不需要重复加载
// app.js
import * as api from './api/index';
App({
onLaunch() {
this.api = api;
},
globalData: {
userInfo: null
}
})
- 在页面中使用
const app = getApp();
Page({
data: {
},
onShow: function () {
app.api.flowerList().then(res=> {
console.log(res);
})
},
})
✔渲染页面
data 和 setData
可以通过控制台的appdata来查看数据
Page({ data: { msg: 'hello', count: 1 }, onLoad(options) { setTimeout(() => { this.setData({ count: 10, msg: '哈哈哈哈哈哈哈' }); }, 2000) }, })
插值表达式
, wxml 中所有的变量都使用
(除了wx:key)
- 如果数组成员是字符串或者数字,
wx:key="index"或者wx:key="*this"
- 如果数组成员是对象, 比如
[{name:'zs',id:1}],wx:key="id"
- 如果数组成员是字符串或者数字,
条件渲染
wx:if
列表渲染
wx:for
默认有 item 和 index双重
wx:for
时需要其中一个指定 item 和 index
✔绑定事件
文档地址 : 小程序框架 /视图层 /事件系统
<button data-username='张三' bindtap="test">点击1</button>
<button data-username='李四' bindtap="test">点击2</button>
Page({
test: function(event) {
// 小程序事件不能像vue那样传参,只能通过自定义属性来传参
let username = event.target.dataset.username;
console.log(username);
},
});
注意: wxml和html一样, 不区分大小写, 页面上的大写, 最后变成了小写
- 常见事件类型
类型 | 触发条件 | 最低版本 |
---|---|---|
touchstart | 手指触摸动作开始 | |
touchmove | 手指触摸后移动 | |
touchcancel | 手指触摸动作被打断,如来电提醒,弹窗 | |
touchend | 手指触摸动作结束 | |
tap | 手指触摸后马上离开 | |
longpress | 手指触摸后,超过 350ms 再离开,如果指定了事件回调函数并触发了这个事件,tap 事件将不被触发 | 1.5.0 |
longtap | 手指触摸后,超过 350ms 再离开(推荐使用 longpress 事件代替) | |
transitionend | 会在 WXSS transition 或 wx.createAnimation 动画结束后触发 | |
animationstart | 会在一个 WXSS animation 动画开始时触发 | |
animationiteration | 会在一个 WXSS animation 一次迭代结束时触发 | |
animationend | 会在一个 WXSS animation 动画完成时触发 | |
touchforcechange | 在支持 3D Touch 的 iPhone 设备,重按时会触发 |
✔open-data 开放数据
https://developers.weixin.qq.com/miniprogram/dev/component/open-data.html
<view class="avatar">
<open-data type="userAvatarUrl"></open-data>
</view>
.avatar{
width: 100rpx;
height: 100rpx;
border-radius: 50%;
border: 1px solid #fff;
overflow: hidden;
margin: 20rpx auto;
}
✔页面跳转
小程序常用两种方式,普通页面跳转和 tab 栏切换(跳转)
(1) 跳转方式一 通过navigator跳转
通过组件 navigator 进行跳转,需要指定跳转类型 open-type
<view class="btn-area">
// 普通页面跳转
<navigator
url="/page/navigate/navigate?title=navigate"
hover-class="navigator-hover"
>跳转到新页面</navigator>
// 跳转到tab栏
<navigator
url="/page/index/index"
open-type="switchTab"
hover-class="other-navigator-hover">切换 Tab</navigator>
// 重定向
<navigator
url="../../redirect/redirect/redirect?title=redirect"
open-type="redirect"
hover-class="other-navigator-hover"
>在当前页打开</navigator
>
// 跳转到小程序
<navigator
target="miniProgram"
open-type="navigate"
app-id=""
path=""
extra-data=""
version="release"
>打开绑定的小程序</navigator
>
</view>
(2) 跳转方式二 通过 js 进行跳转
// 普通页面跳转
wx.navigateTo({
url: "/product/product",
});
// tab栏切换
wx.switchTab({
url: "/index",
});
✔路由传参
(1) 第一种, 参数是基本数据类型
// 列表页
<navigator wx:for="{{flowerList}}" class="flex item pl-10 bg-fff" url="/pages/detail/detail?id={{item.id}}"></navigator>
// 详情页
onLoad: function (options) {
console.log(options.flowerId);
},
(2) 第二种, 参数是引用数据类型
// 参数为对象时,要先将对象转成字符串
toDetail() {
let obj = {useranme: 'zs',age:100};
// 将对象转成json字符串
let query = JSON.stringify(obj);
// 传参
wx.navigateTo({
url: '/pages/detail/detail?query='+query,
})
},
// 获取参数
onLoad: function (options) {
let obj = JSON.parse(options.query);
console.log(obj);
},
注意: wx.swichTab跳转url后不能带参数
✔数据缓存
- 异步方法
wx.setStorage({
key: "key",
data: "value",
});
wx.getStorage({
key: "key",
success(res) {
console.log(res.data);
},
});
- 同步方法
wx.setStorageSync("key", "value");
// 例子
let token = 'asdfasdfasjdflasdjf;asdf;asdfjsak;ldf';
wx.setStorageSync('token',token);
let token = wx.getStorageSync('token');
✔用户授权
知识点
- 用户授权: 录音授权
- 检查用户是否已经授权
- 获取用户信息的授权操作
用户授权功能列表 除了开放数据以外,小程序的很多功能都需要获得用户授权,才可以进行下一步的操作 用户授权的功能列表
(1) 用户授权之录音授权
<button bindtap="shouquan">授权</button>
<button bindtap="luyin">开始录音</button>
Page({
// 授权
shouquan() {
wx.authorize({
// 授权类型
scope: "scope.record", // scope.camera 摄像头
success() {
// 用户已经同意小程序使用录音功能,才能调用录音相关接口
console.log('授权成功');
},
fail() {
console.log('想要使用录音功能, 请先授权');
}
});
},
// 录音
luyin(){
let obj = wx.getRecorderManager();
obj.start({
format: 'mp3'
});
obj.onStart((aa) => {
console.log('开始录音');
})
setTimeout(() => {
obj.stop();
obj.onStop(res => {
console.log(res);
console.log('停止录音')
})
}, 10000)
}
})
(2) 获取用户信息的授权(以前需要, 现在可以直接调用获取用户信息)
- scope.userInfo获取用户信息的授权无法通过js直接调起授权窗口
- 必须绑定点击事件, 用户去点击才能调起授权, 我想应该是腾讯想提醒用户要慎重
- 由于小程序api的调整, 这里获取到头像是一个灰色头像, 若需要获取真正的头像, 详情请看链接
// demo.wxml
<button bindtap="handleClick"> 获取用户信息 </button>
// demo.js
handleClick(e) {
wx.getUserProfile({
desc: '用于完善会员资料',
success: (res) => {
console.log(res);
}
})
},
(3) 获取用户的授权信息
获取用户的当前设置。返回值中只会出现小程序已经向用户请求过的权限
wx.getSetting({
success (res) {
console.log(res.authSetting)
}
})
✔小程序获取位置
(1) 获取位置信息
wx.getLocation({
type: 'wgs84',
success: (res) => {
const latitude = res.latitude;
const longitude = res.longitude;
},
fail: (err) => {
this.setData({
city: '定位失败,请手动选择'
})
}
})
(2) 实际应用:
获取城市名称(需要上一点提供的经纬度)
wx.request({ url: `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=XBZBZ-OBG63-LOD3N-3QR5Q-X6Z2Q-BFBIR`, success: (res) => { let cityName = res.data.result.address_component.city; console.log(cityName) } })
计算两个坐标之间的距离
// 方法定义 lat,lng function GetDistance( lat1, lng1, lat2, lng2){ var radLat1 = lat1*Math.PI / 180.0; var radLat2 = lat2*Math.PI / 180.0; var a = radLat1 - radLat2; var b = lng1*Math.PI / 180.0 - lng2*Math.PI / 180.0; var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) + Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2))); s = s *6378.137 ;// EARTH_RADIUS; s = Math.round(s * 10000) / 10000; return s; } // 调用 return的距离单位为km GetDistance(10.0,113.0,12.0,114.0)
✔微信和小程序支付流程
(1) 简单流程
第一步:调用登录接口,获取到用户的openid等
第二步:Code,价格等发送给后台,后台发送微信生成预支付订单,并且返回预支付订单信息
第三步:小程序拿到预下单订单信息,发起支付,调起支付APP
第四步:后台验证支付结果
(2) 详细流程
商户系统和微信支付系统主要交互:
1、小程序内调用登录接口,获取到用户的openid,api参见公共api【小程序登录API】
2、商户server调用支付统一下单,api参见公共api【统一下单API】
3、商户server调用再次签名,api参见公共api【再次签名】
4、商户server接收支付通知,api参见公共api【支付结果通知API】
5、商户server查询支付结果,api参见公共api【查询订单API】
在第4步里, 小程序端就调起支付页面
wx.requestPayment({
timeStamp: '',
nonceStr: '',
package: '',
signType: 'MD5',
paySign: '',
success (res) { },
fail (res) { }
})
(3) app的支付流程
跟小程序的支付流程大致相同, 只是参数不一样而已
https://www.jb51.net/article/247344.htm
✔uniapp微信小程序登录
微信小程序登录前后端流程
- 前端: 调用wx.login() 获取code
- 前端: 发送请求
- 后端: 获取openid和session_key
- 后端: 根据open和session_key生成token(自定义登录态)
- 前端: 获取token(自定义登录态)并存入缓存
- 前端: 请求数据, 请求头带上token
- 后端: 解析token, 得到openid, 根据openid进行查询数据, 比如购物车(后端)
- 前端: 得到后端返回的数据
(1) 获取code
login() {
uni.login({
provider: 'weixin', //使用微信登录
success: function(res) {
console.log(res.code);
}
});
}
(2) 获取用户信息
获取用户信息必须绑定按钮(不一定按钮, 其它标签也行), 然后通过wx.getUserProfile
来获取
如果头像是灰色, 昵称是'微信用户'请看链接, 关于微信小程序授权后,昵称是“微信用户”,头像是灰色的解决方案
<template>
<view class="text tac fff mt-5" @click="getUserInfo">获取用户信息</view>
</template>
<script>
export default {
methods: {
getUserInfo() {
wx.getUserProfile({
desc: '用户完善个人信息',
success: (res) => {
console.log(resuserInfo);
this.userInfo = res.userInfo;
},
fail: (err) => {
console.log(err);
}
})
}
}
}
</script>
(3) 微信小程序登录
<button bindtap="denglu">登录</button>
import {userLogin} from '../../api/index';
Page({
data: {},
denglu() {
wx.getUserProfile({
desc: '用户信息',
success(res) {
let {iv,encryptedData, userInfo} = res;
wx.login({
success(res) {
let code = res.code;
userLogin({code,iv,encryptedData, userInfo}).then(res=> {
console.log(res);
wx.setStorageSync('token', res.data.token);
})
}
})
},
fail(err) {
console.log(err);
}
});
},
})
✔uniapp 地理位置相关
[腾讯地图API](平时的开发也可以使用百度地图,高度地图):
(1) 地图选址
第一步: hbuildx -> menifest.json -> 微信小程序配置 -> 微信小程序权限配置 -> 位置接口打钩, 描述随便填
第二步: menifest.json 选择最后的源码视图, 在"mp-weixin" 里添加
"mp-weixin" : {
...其它配置,
"requiredPrivateInfos": [
"getLocation",
"chooseLocation"
]
},
第三步: 调用uni.chooseLocation打开地图选址页面
<template>
<view>
<button @click="getAdress">获取位置</button>
<view class="">
{{company}}
</view>
<view class="">
{{adress}}
</view>
</view>
</template>
<script>
export default {
data() {
return {
company: '',
adress: ''
}
},
methods: {
getAdress() {
uni.chooseLocation({
success: res => {
this.adress = res.address;
this.company = res.name;
},
fail: (err) => {
console.log(err);
}
});
}
}
}
</script>
(2) 获取城市名称
申请qq地图密钥
获取经纬度
<template> <button @click="getAdress">获取经纬度</button> </template> <script> export default { methods: { getAdress() { uni.getLocation({ success: function(res) { console.log(res.longitude); console.log(res.latitude); }, fail(err) { console.log(err); } }); } } } </script>
逆地址解析 (根据经纬度获取城市名称)
<template> <button @click="getAdress">获取城市名称</button> </template> <script> export default { methods: { getAdress() { // getLocation获取经纬度 uni.getLocation({ success: function(res) { let longitude = res.longitude; let latitude = res.latitude; let url = `https://apis.map.qq.com/ws/geocoder/v1/?location=${latitude},${longitude}&key=XBZBZ-OBG63-LOD3N-3QR5Q-X6Z2Q-BFBIR`; // 获取城市名称 wx.request({ url: url, success: (res) => { console.log(res); } }) }, fail(err) { console.log(err); } }); } } } </script>